package com.xxl.javawork;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

/**
 *数学计算器的JPanel类，实现数学计算的GUI界面
 * @author xiaxinlin
 * @version 1.0
 * @since jdk1.8
 * @date 2021/1/9 22:39
 */
public class MathCalculator extends JPanel implements ActionListener {

    //按钮
    private String[] KEYS = { "7", "8", "9", "AC", "4", "5", "6", "-", "1", "2", "3", "+", "0", "e", "pi", "/", "sqrt",
            "cos", "x*x", "*", "+/-", "sin", ".", "=" };
    private JButton keys[] = new JButton[KEYS.length];

    //计算过程文本
    private JTextField processText = new JTextField("");
    //计算结果文本
    private JTextField resultText = new JTextField("0");
    //历史记录列表
    private JList History = new JList();
    private JPanel jp1=new JPanel();
    private JPanel jp2=new JPanel();
    //给历史记录添加一个滚动滑条
    private JScrollPane gdt2=new JScrollPane(History);

    private JLabel label = new JLabel("历史记录");

    //计算结果
    private double calResult=0;
    //计算符变量开关
    private boolean calFlag=false;
    //实际计算符
    private String sign="+";
    //添加进历史记录的listmode
    private DefaultListModel listModel;
    private List<String> list;

    /**
     * 数学计算器的构造器
     *
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9
     */
    public MathCalculator() {
        processText.setBounds(0, 18, 255, 50);// 设置文本框大小
        resultText.setBounds(0,70,255,50);
        processText.setEditable(false);
        resultText.setEditable(false);
        processText.setBackground(Color.white);
        resultText.setBackground(Color.white);
        processText.setHorizontalAlignment(JTextField.RIGHT);
        resultText.setHorizontalAlignment(JTextField.RIGHT);
        listModel = new DefaultListModel();
        History.setModel(listModel);
        list = new ArrayList<>();

        History.setBounds(290, 40, 250,370);// 设置文本框大小

        label.setBounds(300, 15, 100, 20);//设置标签位置及大小
        jp2.setBounds(290,40,250,370);//设置面板窗口位置及大小
        jp2.setLayout(new GridLayout());
        jp1.setBounds(20,18,255,115);//设置面板窗口位置及大小
        jp1.setLayout(null);
        resultText.setSelectedTextColor(Color.RED);
        gdt2.setViewportView(History);

        jp1.add(processText);
        jp1.add(resultText);
        jp2.add(gdt2);
        this.add(jp1);
        this.add(jp2);
        this.setLayout(null);
        this.add(label);

        // 放置按钮
        int x = 20, y = 150;
        for (int i = 0; i < KEYS.length; i++)
        {
            keys[i] = new JButton();
            keys[i].setText(KEYS[i]);
            keys[i].setBounds(x, y, 60, 40);
            if (x < 215) {
                x += 65;
            } else {
                x = 20;
                y += 45;
            }
            this.add(keys[i]);
        }
        for (int i = 0; i < KEYS.length; i++)// 每个按钮都注册事件监听器
        {
            keys[i].addActionListener(this);
        }

        History.addListSelectionListener(e->list1ValueChanged(e));
        this.setBounds(0, 0, 567, 480);
    }

    /**
     * 实现actionPerformed的动作监听方法
     *
     * @param e 动作事件，包含容器中所有按钮
     * @return void
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        String btnStr = e.getActionCommand();
        String resultStr = resultText.getText();
        String processStr = processText.getText();
        double result = Double.parseDouble(resultStr);
        if ("+/-".equals(btnStr)){
            if (result!=0){
                result=-result;
                resultText.setText(String.valueOf(result));
                calFlag=false;
            }
        }else if(".".equals(btnStr)){
            if (!resultStr.contains(".")){
                resultText.setText(resultStr+btnStr);
                calFlag=false;
            }
        }else if ("AC".equals(btnStr)){
            cleanCal();
        }else if ("e".equals(btnStr)){
            if ("0".equals(resultStr)||calFlag==true){
                double numE = Math.round(Math.E*100)/100.0;
                resultText.setText(String.valueOf(numE));
                calFlag=false;
            }
        }else if (btnStr.length()==1&&"+-*/".indexOf(btnStr)>=0){
            setCalAll(btnStr);
        }else if ("=".equals(btnStr)){
            if (calFlag==true){
                if (isCal(processStr)){
                    processStr = processStr.subSequence(0,processStr.length()-1)+btnStr;
                    processText.setText(processStr);
                }
            }else {
                setCalAll(btnStr);
            }
            list.add(0,processText.getText()+resultText.getText());
            listModel.add(0,processText.getText()+resultText.getText());
            History.setSelectedIndex(0);
        }else if ("sin".equals(btnStr)){
            setSin();
        }else if ("cos".equals(btnStr)){
            setCos();
        }else if ("x*x".equals(btnStr)){
            setPow();
        }else if ("sqrt".equals(btnStr)){
            setSqrt();
        }else if ("pi".equals(btnStr)){
            if ("0".equals(resultStr)||calFlag==true){
                double numE = Math.round(Math.PI*100)/100.0;
                resultText.setText(String.valueOf(numE));
                calFlag=false;
            }
        }else {
            if (processStr.endsWith("=")){
                cleanCal();
            }
            if ("0".equals(resultText.getText())||calFlag==true){
                resultText.setText(btnStr);
            }else {
                resultText.setText(resultText.getText()+btnStr);
            }
            calFlag=false;
        }
    }

    /**
     * 判断计算过程末尾是否为运算符
     *
     * @param str 按钮事件源的字符串
     * @return boolean 判断结果
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9
     */
    public boolean isCal(String str){
        if (str.endsWith("*")||str.endsWith("-")||str.endsWith("+")||str.endsWith("/")||str.endsWith("%")||str.endsWith("=")){
            return true;
        }
        return false;
    }

    /**
     * 获得计算结果
     *
     * @return double 计算结果
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9
     */
    public double calculatorResult(){
        double result = Double.parseDouble(resultText.getText());
        double dStr=0;
        if ("+".equals(sign)){
            dStr = calResult+result;
        }else if ("-".equals(sign)){
            dStr = calResult-result;
        }else if ("*".equals(sign)){
            dStr = calResult*result;
        }else if ("/".equals(sign)){
            dStr = calResult/result;
        }else if ("=".equals(sign)){
            dStr = result;
            calResult=result;
        }
        return dStr;
    }

    /**
     * 计算符计算结果并设置显示
     *
     * @param btnStr 按钮事件源的字符串
     * @return void
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9 22:33
     */
    public void setCalAll(String btnStr){
        String resultStr = resultText.getText();
        String processStr = processText.getText();
        double result = Double.parseDouble(resultStr);

        if (isCal(processStr)&&calFlag==true){
            processStr = processStr.subSequence(0,processStr.length()-1)+btnStr;
        }else if (calFlag==true){
            processStr = processStr+btnStr;
        }else {
            calResult = calculatorResult();
            if (result<0){
                resultStr="("+resultStr+")";
            }
            if (processStr.endsWith(")")||processStr.endsWith("^2")){
                processStr=processStr+btnStr;
            }else {
                processStr = processStr+resultStr+btnStr;
            }
            resultStr = String.valueOf(calResult);
        }
        sign=btnStr;
        calFlag=true;
        processText.setText(processStr);
        resultText.setText(resultStr);
    }

    /**
     * 清空计算器
     *
     * @return void
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9 22:33
     */
    public void cleanCal(){
        resultText.setText("0");
        processText.setText("");
        calResult=0;
        calFlag=false;
        sign="+";
    }

    /**
     * 实现开方运算
     *
     * @return void
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9 22:33
     */
    public void setSqrt(){
        String resultStr = resultText.getText();
        String processStr = processText.getText();
        if (processStr.endsWith("=")){
            processStr="";
        }
        double result = Double.parseDouble(resultStr);
        if (isCal(processStr)||"".equals(processStr)){
            processStr = processStr+"sqrt("+result+")";
            result = Math.sqrt(result);
        }else {
//            int index = processStr.lastIndexOf("sqrt");
//            processStr = processStr.substring(0,index)+"sqrt("+processStr.substring(index)+")";
            int index = processStr.lastIndexOf(sign);
            if (index<0){
                processStr = "sqrt("+processStr+")";
            }else {
                processStr = processStr.substring(0,index+1)+"sqrt("+processStr.substring(index+1)+")";
            }
            result = Math.sqrt(result);
        }
        processText.setText(processStr);
        resultText.setText(String.valueOf(result));
        calFlag=false;
    }

    /**
     * 实现函数sin运算
     *
     * @return void
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9
     */
    public void setSin(){
        String resultStr = resultText.getText();
        String processStr = processText.getText();
        if (processStr.endsWith("=")){
            processStr="";
        }
        double result = Double.parseDouble(resultStr);
        if (isCal(processStr)||"".equals(processStr)){
            processStr = processStr+"sin("+result+")";
            result = Math.sin(result);
        }else {
            int index = processStr.lastIndexOf(sign);
            if (index<0){
                processStr = "sin("+processStr+")";
            }else {
                processStr = processStr.substring(0,index+1)+"sin("+processStr.substring(index+1)+")";
            }
            result = Math.sin(result);
        }
        processText.setText(processStr);
        resultText.setText(String.valueOf(result));
        calFlag=false;
    }

    /**
     * 实现函数cos运算
     *
     * @return void
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9
     */
    public void setCos(){
        String resultStr = resultText.getText();
        String processStr = processText.getText();
        if (processStr.endsWith("=")){
            processStr="";
        }
        double result = Double.parseDouble(resultStr);
        if (isCal(processStr)||"".equals(processStr)){
            processStr = processStr+"cos("+result+")";
            result = Math.cos(result);
        }else {
            int index = processStr.lastIndexOf(sign);
            if (index<0){
                processStr = "cos("+processStr+")";
            }else {
                processStr = processStr.substring(0,index+1)+"cos("+processStr.substring(index+1)+")";
            }
            result = Math.cos(result);
        }
        processText.setText(processStr);
        resultText.setText(String.valueOf(result));
        calFlag=false;
    }

    /**
     * 实现平方运算
     *
     * @return void
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9
     */
    public void setPow(){
        String resultStr = resultText.getText();
        String processStr = processText.getText();
        if (processStr.endsWith("=")){
            processStr="";
        }
        double result = Double.parseDouble(resultStr);
        if (isCal(processStr)||"".equals(processStr)){
            processStr = processStr+"("+result+")^2";
            result = Math.pow(result,2);
        }else {
            int index = processStr.lastIndexOf(sign);
            if (index<0){
                processStr = "("+processStr+")^2";
            }else {
                processStr = processStr.substring(0,index+1)+"("+processStr.substring(index+1)+")^2";
            }
            result = Math.pow(result,2);
        }
        processText.setText(processStr);
        resultText.setText(String.valueOf(result));
        calFlag=false;
    }

    /**
     * 历史记录JList的动作监控方法
     *
     * @param e jlist动作事件
     * @return void
     * @author xiaxinlin
     * @creed: Talk is cheap,show me the code
     * @date 2021/1/9
     */
    private void list1ValueChanged(ListSelectionEvent e) {
        // TODO add your code here
        //鼠标放开启动
        if (!History.getValueIsAdjusting()){
            //获得选中项的下标
            int index = History.getSelectedIndex();
            String str = list.get(index);
            int strIndex = str.indexOf("=");
            processText.setText(str.substring(0,strIndex+1));
            resultText.setText(str.substring(strIndex+1));
            calResult = Double.parseDouble(resultText.getText());
        }
    }



}
